/**
 * 
 */
package eu.dicode.analysis.demonstrator.service;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.xml.bind.JAXBException;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import de.dicodeproject.analysis.xsd.topics.ObjectFactory;
import de.dicodeproject.analysis.xsd.topics.Queries;
import de.dicodeproject.analysis.xsd.topics.Topic;
import de.dicodeproject.analysis.xsd.topics.Topics;

import eu.dicode.analysis.demonstrator.model.Topiccommand;
import eu.dicodeproject.analysis.xsd.topics.TopicsUtil;

/**
 * @author messner@neofonie.de
 * 
 */
@Component
@Scope("singleton")
public class ConfigruationBasedTopicService implements TopicService {

  private SortedMap<String, Topiccommand> topicCommands = new TreeMap<String, Topiccommand>();
  private String topicFilename;

  /**
   * @see eu.dicode.analysis.demonstrator.service.TopicService#addTopic(eu.dicode.analysis.demonstrator.model.Topiccommand)
   */
  @Override
  public void addTopic(Topiccommand topic) {
    Topiccommand newTopic = new Topiccommand();
    newTopic.setLabel(topic.getLabel());
    newTopic.setQueries(topic.getQueries());
    this.topicCommands.put(topic.getLabel(), newTopic);
    try {
      updateTopics();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  /**
   * @see eu.dicode.analysis.demonstrator.service.TopicService#getTopic(java.lang.String)
   */
  @Override
  public Topiccommand getTopic(String id) {
    return this.topicCommands.get(id);
  }

  /**
   * @see eu.dicode.analysis.demonstrator.service.TopicService#getTopics()
   */
  @Override
  public List<Topiccommand> getTopics() {
    ArrayList<Topiccommand> values = new ArrayList<Topiccommand>(this.topicCommands.size());
    values.addAll(this.topicCommands.values());
    return values;
  }

  /**
   * @see eu.dicode.analysis.demonstrator.service.TopicService#removeTopic()
   */
  @Override
  public void removeTopic(Topiccommand topicToRemove) {
    this.topicCommands.remove(topicToRemove);
    try {
      updateTopics();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  private void updateTopics() throws IOException {
    FileWriter writer = new FileWriter(this.topicFilename);
    ObjectFactory factory = new ObjectFactory();
    Topics topics = factory.createTopics();

    for (Topiccommand toco : this.topicCommands.values()) {

      Topic topic = factory.createTopic();
      topic.setLabel(toco.getLabel());

      Queries queries = factory.createQueries();
      queries.getQuery().addAll(toco.getQueries());
      topic.setQueries(queries);

      topics.getTopic().add(topic);
    }

    try {
      TopicsUtil.marshal(writer, topics);
    } catch (JAXBException e) {
      throw new IOException(e.getMessage(), e);
    } finally {
      writer.close();
    }
  }

  @Resource(name = "topicsConfigurationXmlFile")
  public void setTopicUri(String fullyqualifiedFilename) {
    this.topicFilename = fullyqualifiedFilename;
  }

  @PostConstruct
  public void postConstruct() throws IOException, JAXBException {
    FileReader reader = new FileReader(this.topicFilename);
    Topics topics = TopicsUtil.unmarshal(reader);
    reader.close();

    // convert topics from xml into topiccommands.
    for (Topic topic : topics.getTopic()) {
      Topiccommand toco = new Topiccommand();
      toco.setLabel(topic.getLabel());
      TreeSet<String> queries = new TreeSet<String>();
      for (String query : topic.getQueries().getQuery()) {
	queries.add(query);
      }
      toco.setQueries(queries);
      this.topicCommands.put(topic.getLabel(), toco);
    }
  }
}
